package com.zbj.homemade.spring.factorylifecycle;

import com.zbj.homemade.spring.BeanFactory;
import com.zbj.homemade.spring.annotation.Bean;
import com.zbj.homemade.spring.annotation.Component;
import com.zbj.homemade.spring.annotation.ComponentScan;
import com.zbj.homemade.spring.beans.BeanAnnotationBeanDefinition;
import com.zbj.homemade.spring.beans.BeanDefinition;
import com.zbj.homemade.spring.beans.BeanDefinitionRegistry;
import com.zbj.homemade.spring.beans.ConfigurationBeanDefinition;
import com.zbj.homemade.spring.beans.SimpleBeanDefinition;
import com.zbj.homemade.spring.context.SimpleApplacationContext;
import com.zbj.homemade.spring.utils.ClassUtil;
import com.zbj.homemade.spring.utils.NameUtil;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

/**
 * |                    .  ’   *   ‘  .
 * |               _6                    "     o0000o
 * |  o00o _    .%                         %. o0000000o
 * | o000000o.:                              :(0000000o
 * | o00000os                                  .000000o
 * |  o0000/     <b>不了不了,改需求真的伤身体</>   .000o
 * |    o0o                                       .0o
 * |     y        <b>我认为源代码,就是SkrSkr</>     .
 * |    y                                           ,
 * |   y          <b>小熊猫保佑,代码永不修改</>        ,
 * |   p                            .                 .
 * |   p                           @@.                .
 * |    y                        ;@@@;               .
 * |    \                       ;@@@@;.@.          ,;S
 * |     、                     .@@@@@@;       ,@@@@@
 * |     @\.            .****...*@@@@;     .@@@@@@@@@@@.
 * |    @@@@\.     . @@@@@@@@@@@@@@@;    .@@@@@@@@@@@@@@@.
 * |   @@@@@@@@@.@@@@@@@@@@@@@@@@;   .@@@@@@@@@@@@@@@@@@@@@.
 * |  @@@@@@..@@@@..@@@@@@..@@@@@ .@@...@@@@@..@@..@@@@@..@@.
 * | @@@@@@@@..@..@@@@@@@@@@@@@;.@@@..@..@@@..@@....@@@..@@@@.
 * |@y@@@@@@@@..@@@@@@@@..@@@@i@@@@..@@@..@..@@..@@..@..@@@@n@.
 * |@n@@@@@@@..@@@@@@@@..@@@@@@@@@..@@@@@...@@..@@@@...@@@@@n@@.
 * |@@@@@@@@..@@@@@@@@..@@@@@@@@@..@@@@@@@.@@..@@@@@..@@@@@@@@@@.
 * |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.
 *
 * @program: principle
 * @description: 配置类工厂级别后置处理器
 * @author: Yinn
 * @create: 2019-03-01 17:42
 **/
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {

        for (String bdName : registry.getBeanDefinitionNames()) {

            BeanDefinition bd = registry.getBeanDefinition(bdName);

            if (bd instanceof ConfigurationBeanDefinition) {

                //判断是否为配置类
                ConfigurationBeanDefinition sbd = (ConfigurationBeanDefinition) bd;

                regAll(sbd, registry);

            }

        }
    }

    @Override
    public void postProcessBeanFactory(BeanFactory beanFactory) {

    }


    private void regAll(ConfigurationBeanDefinition sbd, BeanDefinitionRegistry registry) {

        //注册bean 定义
        if (sbd.hasBeanAnnotatedBeanDefinitions()) {
            for (ConcurrentMap.Entry<String, BeanAnnotationBeanDefinition> entry : sbd.getBeans().entrySet()) {

                registry.registerBeanDefinition(entry.getKey(), entry.getValue());

            }
        }

        //扫描 并注册所有打component注解的bean
        if (sbd.hasComponentScanPath()) {

            for (String path : sbd.getComponentScanPath()) {

                if (StringUtils.isNotBlank(path)) {

                    //扫描包 获取classes
                    Map<String, Class<?>> classMap = ClassUtil.getClassMap(path);

                    if (classMap != null && classMap.size() > 0) {

                        for (Map.Entry<String, Class<?>> entry : classMap.entrySet()) {

                            Class<?> clz = entry.getValue();

                            Component c = clz.getAnnotation(Component.class);

                            if (c != null) {
                                String name = c.name();

                                if (StringUtils.isBlank(name))
                                    name = NameUtil.toLowerCaseFirstOne(clz.getSimpleName());

                                registry.registerBeanDefinition(name, new SimpleBeanDefinition(clz));
                            }
                        }

                    }
                }
            }
        }
    }
}
